/*
 *  Copyright 2010 Susanta Tewari.
 *  This file is part of genomemap.
 * 
 *  genomemap is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *  
 *  genomemap is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *  
 *  You should have received a copy of the GNU General Public License
 *  along with genomemap.  If not, see <http://www.gnu.org/licenses/>.
 */
package genomemap.queries;

import genomemap.data.AssignmentManager;
import genomemap.data.Chromosome;
import genomemap.data.GWData;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * @version 1.0 Apr 22, 2010
 * @author Susanta Tewari
 */
public class AssignmentComparison extends Query{

    private List<ChAssignmentInfo> chromosomes = new ArrayList<ChAssignmentInfo>();

    public Object getDataModel() {

        Map root = new HashMap();

        for (Integer linkageGroup : GWData.getInstance().getLinkageGroups())
            this.add(linkageGroup);

        root.put("assignmentComparison", this);

        return root;
    }
    
    public void add(Integer linkageGroup) {
        
        Chromosome chr = Chromosome.getInstance(linkageGroup);

        AssignmentManager am1 = new AssignmentManager(linkageGroup, false);// w/o hybridization
        AssignmentManager am2 = new AssignmentManager(linkageGroup, true);// with hybridization

        Set<String> probes = chr.getProbes();
        Set<String> genes = chr.getGenes();

        ChAssignmentInfo chAssignmentInfo = new ChAssignmentInfo();

        chAssignmentInfo.setLinkageGroup(linkageGroup);
        chAssignmentInfo.setProbeCount(probes.size());
        chAssignmentInfo.setGeneCount(genes.size());

        Set<String> assignedProbes1 = new HashSet<String>(am1.getCloneAssignments().keySet());
        assignedProbes1.retainAll(probes);
        
        Set<String> assignedProbes2 = new HashSet<String>(am2.getCloneAssignments().keySet());
        assignedProbes2.retainAll(probes);

        chAssignmentInfo.setProbesAssigned1Count(assignedProbes1.size());
        chAssignmentInfo.setProbesAssigned2Count(assignedProbes2.size());

        // note that am1 and am2 have same # of genes through am1.getGeneAssignments()
        // they differ only in more enrichment of probes via hybridization
        int assigned_genes_1 = 0, assigned_genes_2 = 0; // genes assigned to probes
        for (String gene : am1.getGeneAssignments().keySet()) {

            Set<String> assigned_non_probes =
                    new HashSet<String>(am1.getGeneAssignments().get(gene));
            assigned_non_probes.removeAll(probes);

            Set<String> assignedProbes1_forGene = new HashSet<String>(
                    am1.getGeneAssignments().get(gene));
            assignedProbes1_forGene.retainAll(probes);

            Set<String> additionalAssignedProbes2 = new HashSet<String>(
                    am2.getGeneAssignments().get(gene));
            additionalAssignedProbes2.retainAll(probes);
            additionalAssignedProbes2.removeAll(assignedProbes1_forGene);

            chAssignmentInfo.addGeneAssignmentInfo(gene, assigned_non_probes,
                    assignedProbes1_forGene, additionalAssignedProbes2);

            if (!assignedProbes1_forGene.isEmpty()) assigned_genes_1++;
            if (!assignedProbes1_forGene.isEmpty() ||!additionalAssignedProbes2.isEmpty())
                assigned_genes_2++;

        }

        chAssignmentInfo.setGenesAssigned1Count(assigned_genes_1);
        chAssignmentInfo.setGenesAssigned2Count(assigned_genes_2);

        chromosomes.add(chAssignmentInfo);
    }

    public List<ChAssignmentInfo> getChromosomes() {
        return chromosomes;
    }

    // <editor-fold defaultstate="collapsed" desc="Total Counts">
    public Integer getTotalProbeCount() {

        int result = 0;

        for (ChAssignmentInfo chAssignmentInfo : chromosomes) {
            result += chAssignmentInfo.getProbeCount();
        }

        return result;
    }

    public Integer getTotalGeneCount() {

        int result = 0;

        for (ChAssignmentInfo chAssignmentInfo : chromosomes) {
            result += chAssignmentInfo.getGeneCount();
        }

        return result;
    }

    public Integer getTotalGenesAssigned1Count() {

        int result = 0;

        for (ChAssignmentInfo chAssignmentInfo : chromosomes) {
            result += chAssignmentInfo.getGenesAssigned1Count();
        }

        return result;
    }

    public Integer getTotalGenesAssigned2Count() {

        int result = 0;

        for (ChAssignmentInfo chAssignmentInfo : chromosomes) {
            result += chAssignmentInfo.getGenesAssigned2Count();
        }

        return result;
    }

    public Integer getTotalProbesAssigned1Count() {

        int result = 0;

        for (ChAssignmentInfo chAssignmentInfo : chromosomes) {
            result += chAssignmentInfo.getProbesAssigned1Count();
        }

        return result;
    }

    public Integer getTotalProbesAssigned2Count() {

        int result = 0;

        for (ChAssignmentInfo chAssignmentInfo : chromosomes) {
            result += chAssignmentInfo.getProbesAssigned2Count();
        }

        return result;
    }// </editor-fold>

    public class ChAssignmentInfo {

        private int linkageGroup;

        private int probeCount;

        private int geneCount;

        private int genesAssignedCount1;

        private int genesAssignedCount2;

        private int probesAssignedCount1;

        private int probesAssignedCount2;

        private List<GeneAssignmentInfo> genes = new ArrayList<GeneAssignmentInfo>();

        public void addGeneAssignmentInfo(String name,
                Set<String> assignedNonProbes,
                Set<String> assignedProbes1,
                Set<String> additionalAssignedProbes2) {

            genes.add(new GeneAssignmentInfo(name, assignedNonProbes, assignedProbes1,
                    additionalAssignedProbes2));
        }

        // <editor-fold defaultstate="collapsed" desc="Bookeeping">
        public int getGeneCount() {
            return geneCount;
        }

        public void setGeneCount(int geneCount) {
            this.geneCount = geneCount;
        }

        public List<GeneAssignmentInfo> getGenes() {
            return genes;
        }

        public void setGenes(List<GeneAssignmentInfo> genes) {
            this.genes = genes;
        }

        public int getGenesAssigned1Count() {
            return genesAssignedCount1;
        }

        public void setGenesAssigned1Count(int genesAssigned1) {
            this.genesAssignedCount1 = genesAssigned1;
        }

        public int getGenesAssigned2Count() {
            return genesAssignedCount2;
        }

        public void setGenesAssigned2Count(int genesAssigned2) {
            this.genesAssignedCount2 = genesAssigned2;
        }

        public int getLinkageGroup() {
            return linkageGroup;
        }

        public void setLinkageGroup(int linkageGroup) {
            this.linkageGroup = linkageGroup;
        }

        public int getProbeCount() {
            return probeCount;
        }

        public void setProbeCount(int probeCount) {
            this.probeCount = probeCount;
        }

        public int getProbesAssigned1Count() {
            return probesAssignedCount1;
        }

        public void setProbesAssigned1Count(int probesAssigned1) {
            this.probesAssignedCount1 = probesAssigned1;
        }

        public int getProbesAssigned2Count() {
            return probesAssignedCount2;
        }

        public void setProbesAssigned2Count(int probesAssigned2) {
            this.probesAssignedCount2 = probesAssigned2;
        }// </editor-fold>

        public class GeneAssignmentInfo {

            private String name;

            private Set<String> assignedNonProbes;

            private Set<String> assignedProbes1;

            private Set<String> additionalAssignedProbes2;

            public GeneAssignmentInfo(String name,
                    Set<String> assignedNonProbes,
                    Set<String> assignedProbes1,
                    Set<String> additionalAssignedProbes2) {
                this.name = name;
                this.assignedNonProbes = assignedNonProbes;
                this.assignedProbes1 = assignedProbes1;
                this.additionalAssignedProbes2 = additionalAssignedProbes2;
            }

            // <editor-fold defaultstate="collapsed" desc="Read-only Properties">
            public String getAdditionalAssignedProbes2() {
                return additionalAssignedProbes2.toString();
            }

            public String getAssignedNonProbes() {
                return assignedNonProbes.toString();
            }

            public String getAssignedProbes1() {
                return assignedProbes1.toString();
            }

            public String getName() {
                return name;
            }// </editor-fold>

        }
    }
}
